import { IncomingMessage, ServerResponse } from 'http';
import { HttpResponse } from "./httpresponse";
import { Socket } from "net";

class HttpRequest extends IncomingMessage {
  public srcReq: IncomingMessage;
  public response: HttpResponse;
  public parameters: Record<string, any> = {};

  constructor(req: IncomingMessage, res: ServerResponse) {
    super(req.socket);
    this.srcReq = req;
    this.response = new HttpResponse(req);
    this.response.init(req, res);
    this.url = req.url;
    this.method = req.method;
    this.initQueryString();
  }

  public async init(): Promise<object> {
    if (this.method !== 'POST') {
      return this.parameters;
    }
    const obj = await this.postHandle();
    if (typeof obj === 'object') {
      Object.keys(obj).forEach((key) => {
        if (this.parameters[key]) {
          if (!Array.isArray(this.parameters[key])) {
            this.parameters[key] = [this.parameters[key]];
          }
          this.parameters[key].push(obj[key]);
        } else {
          this.parameters[key] = obj[key];
        }
      });
    }
    return this.parameters;
  }

  private postHandle(): Promise<object> {
    return new Promise((resolve, reject) => {
      let data = '';
      this.srcReq.on('data', (chunk) => {
        data += chunk;
      });
      this.srcReq.on('end', () => {
        try {
          const parsedData = JSON.parse(data);
          resolve(parsedData);
        } catch (error) {
          reject(error);
        }
      });
      this.srcReq.on('error', (error) => {
        reject(error);
      });
    });
  }

  private initQueryString(): void {
    const { searchParams } = new URL(this.url, `http://${this.headers.host}`);
    searchParams.forEach((value, key) => {
      if (this.parameters[key]) {
        if (!Array.isArray(this.parameters[key])) {
          this.parameters[key] = [this.parameters[key]];
        }
        this.parameters[key].push(value);
      } else {
        this.parameters[key] = value;
      }
    });
  }
}

